//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2022 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

import Foundation
import SotoCore

extension EMRServerless {
    // MARK: Enums

    public enum ApplicationState: String, CustomStringConvertible, Codable, _SotoSendable {
        case created = "CREATED"
        case creating = "CREATING"
        case started = "STARTED"
        case starting = "STARTING"
        case stopped = "STOPPED"
        case stopping = "STOPPING"
        case terminated = "TERMINATED"
        public var description: String { return self.rawValue }
    }

    public enum Architecture: String, CustomStringConvertible, Codable, _SotoSendable {
        case arm64 = "ARM64"
        case x8664 = "X86_64"
        public var description: String { return self.rawValue }
    }

    public enum JobRunState: String, CustomStringConvertible, Codable, _SotoSendable {
        case cancelled = "CANCELLED"
        case cancelling = "CANCELLING"
        case failed = "FAILED"
        case pending = "PENDING"
        case running = "RUNNING"
        case scheduled = "SCHEDULED"
        case submitted = "SUBMITTED"
        case success = "SUCCESS"
        public var description: String { return self.rawValue }
    }

    public enum JobDriver: AWSEncodableShape & AWSDecodableShape, _SotoSendable {
        /// The job driver parameters specified for Hive.
        case hive(Hive)
        /// The job driver parameters specified for Spark.
        case sparkSubmit(SparkSubmit)

        public init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            guard container.allKeys.count == 1, let key = container.allKeys.first else {
                let context = DecodingError.Context(
                    codingPath: container.codingPath,
                    debugDescription: "Expected exactly one key, but got \(container.allKeys.count)"
                )
                throw DecodingError.dataCorrupted(context)
            }
            switch key {
            case .hive:
                let value = try container.decode(Hive.self, forKey: .hive)
                self = .hive(value)
            case .sparkSubmit:
                let value = try container.decode(SparkSubmit.self, forKey: .sparkSubmit)
                self = .sparkSubmit(value)
            }
        }

        public func encode(to encoder: Encoder) throws {
            var container = encoder.container(keyedBy: CodingKeys.self)
            switch self {
            case .hive(let value):
                try container.encode(value, forKey: .hive)
            case .sparkSubmit(let value):
                try container.encode(value, forKey: .sparkSubmit)
            }
        }

        public func validate(name: String) throws {
            switch self {
            case .hive(let value):
                try value.validate(name: "\(name).hive")
            case .sparkSubmit(let value):
                try value.validate(name: "\(name).sparkSubmit")
            }
        }

        private enum CodingKeys: String, CodingKey {
            case hive
            case sparkSubmit
        }
    }

    // MARK: Shapes

    public struct Application: AWSDecodableShape {
        /// The ID of the application.
        public let applicationId: String
        /// The CPU architecture of an application.
        public let architecture: Architecture?
        /// The ARN of the application.
        public let arn: String
        /// The configuration for an application to automatically start on job submission.
        public let autoStartConfiguration: AutoStartConfig?
        /// The configuration for an application to automatically stop after a certain amount of time being idle.
        public let autoStopConfiguration: AutoStopConfig?
        /// The date and time when the application run was created.
        public let createdAt: Date
        /// The initial capacity of the application.
        public let initialCapacity: [String: InitialCapacityConfig]?
        /// The maximum capacity of the application. This is cumulative across all workers at any given point in time during the lifespan of the application is created. No new resources will be created once any one of the defined limits is hit.
        public let maximumCapacity: MaximumAllowedResources?
        /// The name of the application.
        public let name: String?
        /// The network configuration for customer VPC connectivity for the application.
        public let networkConfiguration: NetworkConfiguration?
        /// The EMR release version associated with the application.
        public let releaseLabel: String
        /// The state of the application.
        public let state: ApplicationState
        /// The state details of the application.
        public let stateDetails: String?
        /// The tags assigned to the application.
        public let tags: [String: String]?
        /// The type of application, such as Spark or Hive.
        public let type: String
        /// The date and time when the application run was last updated.
        public let updatedAt: Date

        public init(applicationId: String, architecture: Architecture? = nil, arn: String, autoStartConfiguration: AutoStartConfig? = nil, autoStopConfiguration: AutoStopConfig? = nil, createdAt: Date, initialCapacity: [String: InitialCapacityConfig]? = nil, maximumCapacity: MaximumAllowedResources? = nil, name: String? = nil, networkConfiguration: NetworkConfiguration? = nil, releaseLabel: String, state: ApplicationState, stateDetails: String? = nil, tags: [String: String]? = nil, type: String, updatedAt: Date) {
            self.applicationId = applicationId
            self.architecture = architecture
            self.arn = arn
            self.autoStartConfiguration = autoStartConfiguration
            self.autoStopConfiguration = autoStopConfiguration
            self.createdAt = createdAt
            self.initialCapacity = initialCapacity
            self.maximumCapacity = maximumCapacity
            self.name = name
            self.networkConfiguration = networkConfiguration
            self.releaseLabel = releaseLabel
            self.state = state
            self.stateDetails = stateDetails
            self.tags = tags
            self.type = type
            self.updatedAt = updatedAt
        }

        private enum CodingKeys: String, CodingKey {
            case applicationId
            case architecture
            case arn
            case autoStartConfiguration
            case autoStopConfiguration
            case createdAt
            case initialCapacity
            case maximumCapacity
            case name
            case networkConfiguration
            case releaseLabel
            case state
            case stateDetails
            case tags
            case type
            case updatedAt
        }
    }

    public struct ApplicationSummary: AWSDecodableShape {
        /// The CPU architecture of an application.
        public let architecture: Architecture?
        /// The ARN of the application.
        public let arn: String
        /// The date and time when the application was created.
        public let createdAt: Date
        /// The ID of the application.
        public let id: String
        /// The name of the application.
        public let name: String?
        /// The EMR release version associated with the application.
        public let releaseLabel: String
        /// The state of the application.
        public let state: ApplicationState
        /// The state details of the application.
        public let stateDetails: String?
        /// The type of application, such as Spark or Hive.
        public let type: String
        /// The date and time when the application was last updated.
        public let updatedAt: Date

        public init(architecture: Architecture? = nil, arn: String, createdAt: Date, id: String, name: String? = nil, releaseLabel: String, state: ApplicationState, stateDetails: String? = nil, type: String, updatedAt: Date) {
            self.architecture = architecture
            self.arn = arn
            self.createdAt = createdAt
            self.id = id
            self.name = name
            self.releaseLabel = releaseLabel
            self.state = state
            self.stateDetails = stateDetails
            self.type = type
            self.updatedAt = updatedAt
        }

        private enum CodingKeys: String, CodingKey {
            case architecture
            case arn
            case createdAt
            case id
            case name
            case releaseLabel
            case state
            case stateDetails
            case type
            case updatedAt
        }
    }

    public struct AutoStartConfig: AWSEncodableShape & AWSDecodableShape {
        /// Enables the application to automatically start on job submission. Defaults to true.
        public let enabled: Bool?

        public init(enabled: Bool? = nil) {
            self.enabled = enabled
        }

        private enum CodingKeys: String, CodingKey {
            case enabled
        }
    }

    public struct AutoStopConfig: AWSEncodableShape & AWSDecodableShape {
        /// Enables the application to automatically stop after a certain amount of time being idle. Defaults to true.
        public let enabled: Bool?
        /// The amount of idle time in minutes after which your application will automatically stop. Defaults to 15 minutes.
        public let idleTimeoutMinutes: Int?

        public init(enabled: Bool? = nil, idleTimeoutMinutes: Int? = nil) {
            self.enabled = enabled
            self.idleTimeoutMinutes = idleTimeoutMinutes
        }

        private enum CodingKeys: String, CodingKey {
            case enabled
            case idleTimeoutMinutes
        }
    }

    public struct CancelJobRunRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "applicationId", location: .uri("applicationId")),
            AWSMemberEncoding(label: "jobRunId", location: .uri("jobRunId"))
        ]

        /// The ID of the application on which the job run will be canceled.
        public let applicationId: String
        /// The ID of the job run to cancel.
        public let jobRunId: String

        public init(applicationId: String, jobRunId: String) {
            self.applicationId = applicationId
            self.jobRunId = jobRunId
        }

        public func validate(name: String) throws {
            try self.validate(self.applicationId, name: "applicationId", parent: name, max: 64)
            try self.validate(self.applicationId, name: "applicationId", parent: name, min: 1)
            try self.validate(self.applicationId, name: "applicationId", parent: name, pattern: "^[0-9a-z]+$")
            try self.validate(self.jobRunId, name: "jobRunId", parent: name, max: 64)
            try self.validate(self.jobRunId, name: "jobRunId", parent: name, min: 1)
            try self.validate(self.jobRunId, name: "jobRunId", parent: name, pattern: "^[0-9a-z]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct CancelJobRunResponse: AWSDecodableShape {
        /// The output contains the application ID on which the job run is cancelled.
        public let applicationId: String
        /// The output contains the ID of the cancelled job run.
        public let jobRunId: String

        public init(applicationId: String, jobRunId: String) {
            self.applicationId = applicationId
            self.jobRunId = jobRunId
        }

        private enum CodingKeys: String, CodingKey {
            case applicationId
            case jobRunId
        }
    }

    public struct Configuration: AWSEncodableShape & AWSDecodableShape {
        /// The classification within a configuration.
        public let classification: String
        /// A list of additional configurations to apply within a configuration object.
        public let configurations: [Configuration]?
        /// A set of properties specified within a configuration classification.
        public let properties: [String: String]?

        public init(classification: String, configurations: [Configuration]? = nil, properties: [String: String]? = nil) {
            self.classification = classification
            self.configurations = configurations
            self.properties = properties
        }

        public func validate(name: String) throws {
            try self.validate(self.classification, name: "classification", parent: name, max: 1024)
            try self.validate(self.classification, name: "classification", parent: name, min: 1)
            try self.validate(self.classification, name: "classification", parent: name, pattern: ".*\\S.*")
            try self.configurations?.forEach {
                try $0.validate(name: "\(name).configurations[]")
            }
            try self.validate(self.configurations, name: "configurations", parent: name, max: 100)
            try self.properties?.forEach {
                try validate($0.key, name: "properties.key", parent: name, max: 1024)
                try validate($0.key, name: "properties.key", parent: name, min: 1)
                try validate($0.key, name: "properties.key", parent: name, pattern: ".*\\S.*")
                try validate($0.value, name: "properties[\"\($0.key)\"]", parent: name, max: 1024)
                try validate($0.value, name: "properties[\"\($0.key)\"]", parent: name, min: 1)
                try validate($0.value, name: "properties[\"\($0.key)\"]", parent: name, pattern: ".*\\S.*")
            }
            try self.validate(self.properties, name: "properties", parent: name, max: 100)
        }

        private enum CodingKeys: String, CodingKey {
            case classification
            case configurations
            case properties
        }
    }

    public struct ConfigurationOverrides: AWSEncodableShape & AWSDecodableShape {
        /// The override configurations for the application.
        public let applicationConfiguration: [Configuration]?
        /// The override configurations for monitoring.
        public let monitoringConfiguration: MonitoringConfiguration?

        public init(applicationConfiguration: [Configuration]? = nil, monitoringConfiguration: MonitoringConfiguration? = nil) {
            self.applicationConfiguration = applicationConfiguration
            self.monitoringConfiguration = monitoringConfiguration
        }

        public func validate(name: String) throws {
            try self.applicationConfiguration?.forEach {
                try $0.validate(name: "\(name).applicationConfiguration[]")
            }
            try self.validate(self.applicationConfiguration, name: "applicationConfiguration", parent: name, max: 100)
            try self.monitoringConfiguration?.validate(name: "\(name).monitoringConfiguration")
        }

        private enum CodingKeys: String, CodingKey {
            case applicationConfiguration
            case monitoringConfiguration
        }
    }

    public struct CreateApplicationRequest: AWSEncodableShape {
        /// The CPU architecture of an application.
        public let architecture: Architecture?
        /// The configuration for an application to automatically start on job submission.
        public let autoStartConfiguration: AutoStartConfig?
        /// The configuration for an application to automatically stop after a certain amount of time being idle.
        public let autoStopConfiguration: AutoStopConfig?
        /// The client idempotency token of the application to create. Its value must be unique for each request.
        public let clientToken: String
        /// The capacity to initialize when the application is created.
        public let initialCapacity: [String: InitialCapacityConfig]?
        /// The maximum capacity to allocate when the application is created. This is cumulative across all workers at any given point in time, not just when an application is created. No new resources will be created once any one of the defined limits is hit.
        public let maximumCapacity: MaximumAllowedResources?
        /// The name of the application.
        public let name: String?
        /// The network configuration for customer VPC connectivity.
        public let networkConfiguration: NetworkConfiguration?
        /// The EMR release version associated with the application.
        public let releaseLabel: String
        /// The tags assigned to the application.
        public let tags: [String: String]?
        /// The type of application you want to start, such as Spark or Hive.
        public let type: String

        public init(architecture: Architecture? = nil, autoStartConfiguration: AutoStartConfig? = nil, autoStopConfiguration: AutoStopConfig? = nil, clientToken: String = CreateApplicationRequest.idempotencyToken(), initialCapacity: [String: InitialCapacityConfig]? = nil, maximumCapacity: MaximumAllowedResources? = nil, name: String? = nil, networkConfiguration: NetworkConfiguration? = nil, releaseLabel: String, tags: [String: String]? = nil, type: String) {
            self.architecture = architecture
            self.autoStartConfiguration = autoStartConfiguration
            self.autoStopConfiguration = autoStopConfiguration
            self.clientToken = clientToken
            self.initialCapacity = initialCapacity
            self.maximumCapacity = maximumCapacity
            self.name = name
            self.networkConfiguration = networkConfiguration
            self.releaseLabel = releaseLabel
            self.tags = tags
            self.type = type
        }

        public func validate(name: String) throws {
            try self.validate(self.clientToken, name: "clientToken", parent: name, max: 64)
            try self.validate(self.clientToken, name: "clientToken", parent: name, min: 1)
            try self.validate(self.clientToken, name: "clientToken", parent: name, pattern: "^[A-Za-z0-9._-]+$")
            try self.initialCapacity?.forEach {
                try validate($0.key, name: "initialCapacity.key", parent: name, max: 50)
                try validate($0.key, name: "initialCapacity.key", parent: name, min: 1)
                try validate($0.key, name: "initialCapacity.key", parent: name, pattern: "^[a-zA-Z]+[-_]*[a-zA-Z]+$")
                try $0.value.validate(name: "\(name).initialCapacity[\"\($0.key)\"]")
            }
            try self.validate(self.initialCapacity, name: "initialCapacity", parent: name, max: 10)
            try self.maximumCapacity?.validate(name: "\(name).maximumCapacity")
            try self.validate(self.name, name: "name", parent: name, max: 64)
            try self.validate(self.name, name: "name", parent: name, min: 1)
            try self.validate(self.name, name: "name", parent: name, pattern: "^[A-Za-z0-9._/#-]+$")
            try self.networkConfiguration?.validate(name: "\(name).networkConfiguration")
            try self.validate(self.releaseLabel, name: "releaseLabel", parent: name, max: 64)
            try self.validate(self.releaseLabel, name: "releaseLabel", parent: name, min: 1)
            try self.validate(self.releaseLabel, name: "releaseLabel", parent: name, pattern: "^[A-Za-z0-9._/-]+$")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^[A-Za-z0-9 /_.:=+@-]+$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, pattern: "^[A-Za-z0-9 /_.:=+@-]*$")
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 200)
            try self.validate(self.type, name: "type", parent: name, max: 64)
            try self.validate(self.type, name: "type", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case architecture
            case autoStartConfiguration
            case autoStopConfiguration
            case clientToken
            case initialCapacity
            case maximumCapacity
            case name
            case networkConfiguration
            case releaseLabel
            case tags
            case type
        }
    }

    public struct CreateApplicationResponse: AWSDecodableShape {
        /// The output contains the application ID.
        public let applicationId: String
        /// The output contains the ARN of the application.
        public let arn: String
        /// The output contains the name of the application.
        public let name: String?

        public init(applicationId: String, arn: String, name: String? = nil) {
            self.applicationId = applicationId
            self.arn = arn
            self.name = name
        }

        private enum CodingKeys: String, CodingKey {
            case applicationId
            case arn
            case name
        }
    }

    public struct DeleteApplicationRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "applicationId", location: .uri("applicationId"))
        ]

        /// The ID of the application that will be deleted.
        public let applicationId: String

        public init(applicationId: String) {
            self.applicationId = applicationId
        }

        public func validate(name: String) throws {
            try self.validate(self.applicationId, name: "applicationId", parent: name, max: 64)
            try self.validate(self.applicationId, name: "applicationId", parent: name, min: 1)
            try self.validate(self.applicationId, name: "applicationId", parent: name, pattern: "^[0-9a-z]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct DeleteApplicationResponse: AWSDecodableShape {
        public init() {}
    }

    public struct GetApplicationRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "applicationId", location: .uri("applicationId"))
        ]

        /// The ID of the application that will be described.
        public let applicationId: String

        public init(applicationId: String) {
            self.applicationId = applicationId
        }

        public func validate(name: String) throws {
            try self.validate(self.applicationId, name: "applicationId", parent: name, max: 64)
            try self.validate(self.applicationId, name: "applicationId", parent: name, min: 1)
            try self.validate(self.applicationId, name: "applicationId", parent: name, pattern: "^[0-9a-z]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetApplicationResponse: AWSDecodableShape {
        /// The output displays information about the specified application.
        public let application: Application

        public init(application: Application) {
            self.application = application
        }

        private enum CodingKeys: String, CodingKey {
            case application
        }
    }

    public struct GetDashboardForJobRunRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "applicationId", location: .uri("applicationId")),
            AWSMemberEncoding(label: "jobRunId", location: .uri("jobRunId"))
        ]

        /// The ID of the application.
        public let applicationId: String
        /// The ID of the job run.
        public let jobRunId: String

        public init(applicationId: String, jobRunId: String) {
            self.applicationId = applicationId
            self.jobRunId = jobRunId
        }

        public func validate(name: String) throws {
            try self.validate(self.applicationId, name: "applicationId", parent: name, max: 64)
            try self.validate(self.applicationId, name: "applicationId", parent: name, min: 1)
            try self.validate(self.applicationId, name: "applicationId", parent: name, pattern: "^[0-9a-z]+$")
            try self.validate(self.jobRunId, name: "jobRunId", parent: name, max: 64)
            try self.validate(self.jobRunId, name: "jobRunId", parent: name, min: 1)
            try self.validate(self.jobRunId, name: "jobRunId", parent: name, pattern: "^[0-9a-z]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetDashboardForJobRunResponse: AWSDecodableShape {
        /// The URL to view job run's dashboard.
        public let url: String?

        public init(url: String? = nil) {
            self.url = url
        }

        private enum CodingKeys: String, CodingKey {
            case url
        }
    }

    public struct GetJobRunRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "applicationId", location: .uri("applicationId")),
            AWSMemberEncoding(label: "jobRunId", location: .uri("jobRunId"))
        ]

        /// The ID of the application on which the job run is submitted.
        public let applicationId: String
        /// The ID of the job run.
        public let jobRunId: String

        public init(applicationId: String, jobRunId: String) {
            self.applicationId = applicationId
            self.jobRunId = jobRunId
        }

        public func validate(name: String) throws {
            try self.validate(self.applicationId, name: "applicationId", parent: name, max: 64)
            try self.validate(self.applicationId, name: "applicationId", parent: name, min: 1)
            try self.validate(self.applicationId, name: "applicationId", parent: name, pattern: "^[0-9a-z]+$")
            try self.validate(self.jobRunId, name: "jobRunId", parent: name, max: 64)
            try self.validate(self.jobRunId, name: "jobRunId", parent: name, min: 1)
            try self.validate(self.jobRunId, name: "jobRunId", parent: name, pattern: "^[0-9a-z]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct GetJobRunResponse: AWSDecodableShape {
        /// The output displays information about the job run.
        public let jobRun: JobRun

        public init(jobRun: JobRun) {
            self.jobRun = jobRun
        }

        private enum CodingKeys: String, CodingKey {
            case jobRun
        }
    }

    public struct Hive: AWSEncodableShape & AWSDecodableShape {
        /// The query file for the Hive job run.
        public let initQueryFile: String?
        /// The parameters for the Hive job run.
        public let parameters: String?
        /// The query for the Hive job run.
        public let query: String

        public init(initQueryFile: String? = nil, parameters: String? = nil, query: String) {
            self.initQueryFile = initQueryFile
            self.parameters = parameters
            self.query = query
        }

        public func validate(name: String) throws {
            try self.validate(self.initQueryFile, name: "initQueryFile", parent: name, max: 256)
            try self.validate(self.initQueryFile, name: "initQueryFile", parent: name, min: 1)
            try self.validate(self.initQueryFile, name: "initQueryFile", parent: name, pattern: ".*\\S.*")
            try self.validate(self.parameters, name: "parameters", parent: name, max: 102_400)
            try self.validate(self.parameters, name: "parameters", parent: name, min: 1)
            try self.validate(self.parameters, name: "parameters", parent: name, pattern: ".*\\S.*")
            try self.validate(self.query, name: "query", parent: name, max: 10280)
            try self.validate(self.query, name: "query", parent: name, min: 1)
            try self.validate(self.query, name: "query", parent: name, pattern: ".*\\S.*")
        }

        private enum CodingKeys: String, CodingKey {
            case initQueryFile
            case parameters
            case query
        }
    }

    public struct InitialCapacityConfig: AWSEncodableShape & AWSDecodableShape {
        /// The resource configuration of the initial capacity configuration.
        public let workerConfiguration: WorkerResourceConfig?
        /// The number of workers in the initial capacity configuration.
        public let workerCount: Int64

        public init(workerConfiguration: WorkerResourceConfig? = nil, workerCount: Int64) {
            self.workerConfiguration = workerConfiguration
            self.workerCount = workerCount
        }

        public func validate(name: String) throws {
            try self.workerConfiguration?.validate(name: "\(name).workerConfiguration")
            try self.validate(self.workerCount, name: "workerCount", parent: name, max: 1_000_000)
            try self.validate(self.workerCount, name: "workerCount", parent: name, min: 1)
        }

        private enum CodingKeys: String, CodingKey {
            case workerConfiguration
            case workerCount
        }
    }

    public struct JobRun: AWSDecodableShape {
        /// The ID of the application the job is running on.
        public let applicationId: String
        /// The execution role ARN of the job run.
        public let arn: String
        /// The configuration settings that are used to override default configuration.
        public let configurationOverrides: ConfigurationOverrides?
        /// The date and time when the job run was created.
        public let createdAt: Date
        /// The user who created the job run.
        public let createdBy: String
        /// The execution role ARN of the job run.
        public let executionRole: String
        /// The job driver for the job run.
        public let jobDriver: JobDriver
        /// The ID of the job run.
        public let jobRunId: String
        /// The optional job run name. This doesn't have to be unique.
        public let name: String?
        public let networkConfiguration: NetworkConfiguration?
        /// The EMR release version associated with the application your job is running on.
        public let releaseLabel: String
        /// The state of the job run.
        public let state: JobRunState
        /// The state details of the job run.
        public let stateDetails: String
        /// The tags assigned to the job run.
        public let tags: [String: String]?
        /// The job run total execution duration in seconds. This field is only available for job runs in a COMPLETED, FAILED, or CANCELLED state.
        public let totalExecutionDurationSeconds: Int?
        /// The aggregate vCPU, memory, and storage resources used from the time job start executing till the time job is terminated, rounded up to the nearest second.
        public let totalResourceUtilization: TotalResourceUtilization?
        /// The date and time when the job run was updated.
        public let updatedAt: Date

        public init(applicationId: String, arn: String, configurationOverrides: ConfigurationOverrides? = nil, createdAt: Date, createdBy: String, executionRole: String, jobDriver: JobDriver, jobRunId: String, name: String? = nil, networkConfiguration: NetworkConfiguration? = nil, releaseLabel: String, state: JobRunState, stateDetails: String, tags: [String: String]? = nil, totalExecutionDurationSeconds: Int? = nil, totalResourceUtilization: TotalResourceUtilization? = nil, updatedAt: Date) {
            self.applicationId = applicationId
            self.arn = arn
            self.configurationOverrides = configurationOverrides
            self.createdAt = createdAt
            self.createdBy = createdBy
            self.executionRole = executionRole
            self.jobDriver = jobDriver
            self.jobRunId = jobRunId
            self.name = name
            self.networkConfiguration = networkConfiguration
            self.releaseLabel = releaseLabel
            self.state = state
            self.stateDetails = stateDetails
            self.tags = tags
            self.totalExecutionDurationSeconds = totalExecutionDurationSeconds
            self.totalResourceUtilization = totalResourceUtilization
            self.updatedAt = updatedAt
        }

        private enum CodingKeys: String, CodingKey {
            case applicationId
            case arn
            case configurationOverrides
            case createdAt
            case createdBy
            case executionRole
            case jobDriver
            case jobRunId
            case name
            case networkConfiguration
            case releaseLabel
            case state
            case stateDetails
            case tags
            case totalExecutionDurationSeconds
            case totalResourceUtilization
            case updatedAt
        }
    }

    public struct JobRunSummary: AWSDecodableShape {
        /// The ID of the application the job is running on.
        public let applicationId: String
        /// The ARN of the job run.
        public let arn: String
        /// The date and time when the job run was created.
        public let createdAt: Date
        /// The user who created the job run.
        public let createdBy: String
        /// The execution role ARN of the job run.
        public let executionRole: String
        /// The ID of the job run.
        public let id: String
        /// The optional job run name. This doesn't have to be unique.
        public let name: String?
        /// The EMR release version associated with the application your job is running on.
        public let releaseLabel: String
        /// The state of the job run.
        public let state: JobRunState
        /// The state details of the job run.
        public let stateDetails: String
        /// The type of job run, such as Spark or Hive.
        public let type: String?
        /// The date and time when the job run was last updated.
        public let updatedAt: Date

        public init(applicationId: String, arn: String, createdAt: Date, createdBy: String, executionRole: String, id: String, name: String? = nil, releaseLabel: String, state: JobRunState, stateDetails: String, type: String? = nil, updatedAt: Date) {
            self.applicationId = applicationId
            self.arn = arn
            self.createdAt = createdAt
            self.createdBy = createdBy
            self.executionRole = executionRole
            self.id = id
            self.name = name
            self.releaseLabel = releaseLabel
            self.state = state
            self.stateDetails = stateDetails
            self.type = type
            self.updatedAt = updatedAt
        }

        private enum CodingKeys: String, CodingKey {
            case applicationId
            case arn
            case createdAt
            case createdBy
            case executionRole
            case id
            case name
            case releaseLabel
            case state
            case stateDetails
            case type
            case updatedAt
        }
    }

    public struct ListApplicationsRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "maxResults", location: .querystring("maxResults")),
            AWSMemberEncoding(label: "nextToken", location: .querystring("nextToken")),
            AWSMemberEncoding(label: "states", location: .querystring("states"))
        ]

        /// The maximum number of applications that can be listed.
        public let maxResults: Int?
        /// The token for the next set of application results.
        public let nextToken: String?
        /// An optional filter for application states. Note that if this filter contains multiple states, the resulting list will be grouped by the state.
        public let states: [ApplicationState]?

        public init(maxResults: Int? = nil, nextToken: String? = nil, states: [ApplicationState]? = nil) {
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.states = states
        }

        public func validate(name: String) throws {
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, pattern: "^[A-Za-z0-9_=-]+$")
            try self.validate(self.states, name: "states", parent: name, max: 7)
            try self.validate(self.states, name: "states", parent: name, min: 1)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListApplicationsResponse: AWSDecodableShape {
        /// The output lists the specified applications.
        public let applications: [ApplicationSummary]
        /// The output displays the token for the next set of application results. This is required for pagination and is available as a response of the previous request.
        public let nextToken: String?

        public init(applications: [ApplicationSummary], nextToken: String? = nil) {
            self.applications = applications
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case applications
            case nextToken
        }
    }

    public struct ListJobRunsRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "applicationId", location: .uri("applicationId")),
            AWSMemberEncoding(label: "createdAtAfter", location: .querystring("createdAtAfter")),
            AWSMemberEncoding(label: "createdAtBefore", location: .querystring("createdAtBefore")),
            AWSMemberEncoding(label: "maxResults", location: .querystring("maxResults")),
            AWSMemberEncoding(label: "nextToken", location: .querystring("nextToken")),
            AWSMemberEncoding(label: "states", location: .querystring("states"))
        ]

        /// The ID of the application for which to list the job run.
        public let applicationId: String
        /// The lower bound of the option to filter by creation date and time.
        public let createdAtAfter: Date?
        /// The upper bound of the option to filter by creation date and time.
        public let createdAtBefore: Date?
        /// The maximum number of job runs that can be listed.
        public let maxResults: Int?
        /// The token for the next set of job run results.
        public let nextToken: String?
        /// An optional filter for job run states. Note that if this filter contains multiple states, the resulting list will be grouped by the state.
        public let states: [JobRunState]?

        public init(applicationId: String, createdAtAfter: Date? = nil, createdAtBefore: Date? = nil, maxResults: Int? = nil, nextToken: String? = nil, states: [JobRunState]? = nil) {
            self.applicationId = applicationId
            self.createdAtAfter = createdAtAfter
            self.createdAtBefore = createdAtBefore
            self.maxResults = maxResults
            self.nextToken = nextToken
            self.states = states
        }

        public func validate(name: String) throws {
            try self.validate(self.applicationId, name: "applicationId", parent: name, max: 64)
            try self.validate(self.applicationId, name: "applicationId", parent: name, min: 1)
            try self.validate(self.applicationId, name: "applicationId", parent: name, pattern: "^[0-9a-z]+$")
            try self.validate(self.nextToken, name: "nextToken", parent: name, max: 1024)
            try self.validate(self.nextToken, name: "nextToken", parent: name, min: 1)
            try self.validate(self.nextToken, name: "nextToken", parent: name, pattern: "^[A-Za-z0-9_=-]+$")
            try self.validate(self.states, name: "states", parent: name, max: 8)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListJobRunsResponse: AWSDecodableShape {
        /// The output lists information about the specified job runs.
        public let jobRuns: [JobRunSummary]
        /// The output displays the token for the next set of job run results. This is required for pagination and is available as a response of the previous request.
        public let nextToken: String?

        public init(jobRuns: [JobRunSummary], nextToken: String? = nil) {
            self.jobRuns = jobRuns
            self.nextToken = nextToken
        }

        private enum CodingKeys: String, CodingKey {
            case jobRuns
            case nextToken
        }
    }

    public struct ListTagsForResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("resourceArn"))
        ]

        /// The Amazon Resource Name (ARN) that identifies the resource to list the tags for. Currently, the supported resources are Amazon EMR Serverless applications and job runs.
        public let resourceArn: String

        public init(resourceArn: String) {
            self.resourceArn = resourceArn
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 1024)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 60)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:(aws[a-zA-Z0-9-]*):emr-serverless:.+:(\\d{12}):\\/applications\\/[0-9a-zA-Z]+(\\/jobruns\\/[0-9a-zA-Z]+)?$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct ListTagsForResourceResponse: AWSDecodableShape {
        /// The tags for the resource.
        public let tags: [String: String]?

        public init(tags: [String: String]? = nil) {
            self.tags = tags
        }

        private enum CodingKeys: String, CodingKey {
            case tags
        }
    }

    public struct ManagedPersistenceMonitoringConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// Enables managed logging and defaults to true. If set to false, managed logging will be turned off.
        public let enabled: Bool?
        /// The KMS key ARN to encrypt the logs stored in managed log persistence.
        public let encryptionKeyArn: String?

        public init(enabled: Bool? = nil, encryptionKeyArn: String? = nil) {
            self.enabled = enabled
            self.encryptionKeyArn = encryptionKeyArn
        }

        public func validate(name: String) throws {
            try self.validate(self.encryptionKeyArn, name: "encryptionKeyArn", parent: name, max: 2048)
            try self.validate(self.encryptionKeyArn, name: "encryptionKeyArn", parent: name, min: 20)
            try self.validate(self.encryptionKeyArn, name: "encryptionKeyArn", parent: name, pattern: "^arn:(aws[a-zA-Z0-9-]*):kms:[a-zA-Z0-9\\-]*:(\\d{12})?:key\\/[a-zA-Z0-9-]+$")
        }

        private enum CodingKeys: String, CodingKey {
            case enabled
            case encryptionKeyArn
        }
    }

    public struct MaximumAllowedResources: AWSEncodableShape & AWSDecodableShape {
        /// The maximum allowed CPU for an application.
        public let cpu: String
        /// The maximum allowed disk for an application.
        public let disk: String?
        /// The maximum allowed resources for an application.
        public let memory: String

        public init(cpu: String, disk: String? = nil, memory: String) {
            self.cpu = cpu
            self.disk = disk
            self.memory = memory
        }

        public func validate(name: String) throws {
            try self.validate(self.cpu, name: "cpu", parent: name, max: 15)
            try self.validate(self.cpu, name: "cpu", parent: name, min: 1)
            try self.validate(self.cpu, name: "cpu", parent: name, pattern: "^[1-9][0-9]*(\\s)?(vCPU|vcpu|VCPU)?$")
            try self.validate(self.disk, name: "disk", parent: name, max: 15)
            try self.validate(self.disk, name: "disk", parent: name, min: 1)
            try self.validate(self.disk, name: "disk", parent: name, pattern: "^[1-9][0-9]*(\\s)?(GB|gb|gB|Gb)$")
            try self.validate(self.memory, name: "memory", parent: name, max: 15)
            try self.validate(self.memory, name: "memory", parent: name, min: 1)
            try self.validate(self.memory, name: "memory", parent: name, pattern: "^[1-9][0-9]*(\\s)?(GB|gb|gB|Gb)?$")
        }

        private enum CodingKeys: String, CodingKey {
            case cpu
            case disk
            case memory
        }
    }

    public struct MonitoringConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// The managed log persistence configuration for a job run.
        public let managedPersistenceMonitoringConfiguration: ManagedPersistenceMonitoringConfiguration?
        /// The Amazon S3 configuration for monitoring log publishing.
        public let s3MonitoringConfiguration: S3MonitoringConfiguration?

        public init(managedPersistenceMonitoringConfiguration: ManagedPersistenceMonitoringConfiguration? = nil, s3MonitoringConfiguration: S3MonitoringConfiguration? = nil) {
            self.managedPersistenceMonitoringConfiguration = managedPersistenceMonitoringConfiguration
            self.s3MonitoringConfiguration = s3MonitoringConfiguration
        }

        public func validate(name: String) throws {
            try self.managedPersistenceMonitoringConfiguration?.validate(name: "\(name).managedPersistenceMonitoringConfiguration")
            try self.s3MonitoringConfiguration?.validate(name: "\(name).s3MonitoringConfiguration")
        }

        private enum CodingKeys: String, CodingKey {
            case managedPersistenceMonitoringConfiguration
            case s3MonitoringConfiguration
        }
    }

    public struct NetworkConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// The array of security group Ids for customer VPC connectivity.
        public let securityGroupIds: [String]?
        /// The array of subnet Ids for customer VPC connectivity.
        public let subnetIds: [String]?

        public init(securityGroupIds: [String]? = nil, subnetIds: [String]? = nil) {
            self.securityGroupIds = securityGroupIds
            self.subnetIds = subnetIds
        }

        public func validate(name: String) throws {
            try self.securityGroupIds?.forEach {
                try validate($0, name: "securityGroupIds[]", parent: name, max: 32)
                try validate($0, name: "securityGroupIds[]", parent: name, min: 1)
                try validate($0, name: "securityGroupIds[]", parent: name, pattern: "^[-0-9a-zA-Z]+")
            }
            try self.validate(self.securityGroupIds, name: "securityGroupIds", parent: name, max: 5)
            try self.subnetIds?.forEach {
                try validate($0, name: "subnetIds[]", parent: name, max: 32)
                try validate($0, name: "subnetIds[]", parent: name, min: 1)
                try validate($0, name: "subnetIds[]", parent: name, pattern: "^[-0-9a-zA-Z]+")
            }
            try self.validate(self.subnetIds, name: "subnetIds", parent: name, max: 16)
        }

        private enum CodingKeys: String, CodingKey {
            case securityGroupIds
            case subnetIds
        }
    }

    public struct S3MonitoringConfiguration: AWSEncodableShape & AWSDecodableShape {
        /// The KMS key ARN to encrypt the logs published to the given Amazon S3 destination.
        public let encryptionKeyArn: String?
        /// The Amazon S3 destination URI for log publishing.
        public let logUri: String?

        public init(encryptionKeyArn: String? = nil, logUri: String? = nil) {
            self.encryptionKeyArn = encryptionKeyArn
            self.logUri = logUri
        }

        public func validate(name: String) throws {
            try self.validate(self.encryptionKeyArn, name: "encryptionKeyArn", parent: name, max: 2048)
            try self.validate(self.encryptionKeyArn, name: "encryptionKeyArn", parent: name, min: 20)
            try self.validate(self.encryptionKeyArn, name: "encryptionKeyArn", parent: name, pattern: "^arn:(aws[a-zA-Z0-9-]*):kms:[a-zA-Z0-9\\-]*:(\\d{12})?:key\\/[a-zA-Z0-9-]+$")
            try self.validate(self.logUri, name: "logUri", parent: name, max: 10280)
            try self.validate(self.logUri, name: "logUri", parent: name, min: 1)
            try self.validate(self.logUri, name: "logUri", parent: name, pattern: "[\\u0020-\\uD7FF\\uE000-\\uFFFD\\uD800\\uDBFF-\\uDC00\\uDFFF\\r\\n\\t]*")
        }

        private enum CodingKeys: String, CodingKey {
            case encryptionKeyArn
            case logUri
        }
    }

    public struct SparkSubmit: AWSEncodableShape & AWSDecodableShape {
        /// The entry point for the Spark submit job run.
        public let entryPoint: String
        /// The arguments for the Spark submit job run.
        public let entryPointArguments: [String]?
        /// The parameters for the Spark submit job run.
        public let sparkSubmitParameters: String?

        public init(entryPoint: String, entryPointArguments: [String]? = nil, sparkSubmitParameters: String? = nil) {
            self.entryPoint = entryPoint
            self.entryPointArguments = entryPointArguments
            self.sparkSubmitParameters = sparkSubmitParameters
        }

        public func validate(name: String) throws {
            try self.validate(self.entryPoint, name: "entryPoint", parent: name, max: 256)
            try self.validate(self.entryPoint, name: "entryPoint", parent: name, min: 1)
            try self.validate(self.entryPoint, name: "entryPoint", parent: name, pattern: ".*\\S.*")
            try self.entryPointArguments?.forEach {
                try validate($0, name: "entryPointArguments[]", parent: name, max: 10280)
                try validate($0, name: "entryPointArguments[]", parent: name, min: 1)
                try validate($0, name: "entryPointArguments[]", parent: name, pattern: ".*\\S.*")
            }
            try self.validate(self.sparkSubmitParameters, name: "sparkSubmitParameters", parent: name, max: 102_400)
            try self.validate(self.sparkSubmitParameters, name: "sparkSubmitParameters", parent: name, min: 1)
            try self.validate(self.sparkSubmitParameters, name: "sparkSubmitParameters", parent: name, pattern: ".*\\S.*")
        }

        private enum CodingKeys: String, CodingKey {
            case entryPoint
            case entryPointArguments
            case sparkSubmitParameters
        }
    }

    public struct StartApplicationRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "applicationId", location: .uri("applicationId"))
        ]

        /// The ID of the application to start.
        public let applicationId: String

        public init(applicationId: String) {
            self.applicationId = applicationId
        }

        public func validate(name: String) throws {
            try self.validate(self.applicationId, name: "applicationId", parent: name, max: 64)
            try self.validate(self.applicationId, name: "applicationId", parent: name, min: 1)
            try self.validate(self.applicationId, name: "applicationId", parent: name, pattern: "^[0-9a-z]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct StartApplicationResponse: AWSDecodableShape {
        public init() {}
    }

    public struct StartJobRunRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "applicationId", location: .uri("applicationId"))
        ]

        /// The ID of the application on which to run the job.
        public let applicationId: String
        /// The client idempotency token of the job run to start. Its value must be unique for each request.
        public let clientToken: String
        /// The configuration overrides for the job run.
        public let configurationOverrides: ConfigurationOverrides?
        /// The execution role ARN for the job run.
        public let executionRoleArn: String
        /// The maximum duration for the job run to run. If the job run runs beyond this duration, it will be automatically cancelled.
        public let executionTimeoutMinutes: Int64?
        /// The job driver for the job run.
        public let jobDriver: JobDriver?
        /// The optional job run name. This doesn't have to be unique.
        public let name: String?
        /// The tags assigned to the job run.
        public let tags: [String: String]?

        public init(applicationId: String, clientToken: String = StartJobRunRequest.idempotencyToken(), configurationOverrides: ConfigurationOverrides? = nil, executionRoleArn: String, executionTimeoutMinutes: Int64? = nil, jobDriver: JobDriver? = nil, name: String? = nil, tags: [String: String]? = nil) {
            self.applicationId = applicationId
            self.clientToken = clientToken
            self.configurationOverrides = configurationOverrides
            self.executionRoleArn = executionRoleArn
            self.executionTimeoutMinutes = executionTimeoutMinutes
            self.jobDriver = jobDriver
            self.name = name
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.applicationId, name: "applicationId", parent: name, max: 64)
            try self.validate(self.applicationId, name: "applicationId", parent: name, min: 1)
            try self.validate(self.applicationId, name: "applicationId", parent: name, pattern: "^[0-9a-z]+$")
            try self.validate(self.clientToken, name: "clientToken", parent: name, max: 64)
            try self.validate(self.clientToken, name: "clientToken", parent: name, min: 1)
            try self.validate(self.clientToken, name: "clientToken", parent: name, pattern: "^[A-Za-z0-9._-]+$")
            try self.configurationOverrides?.validate(name: "\(name).configurationOverrides")
            try self.validate(self.executionRoleArn, name: "executionRoleArn", parent: name, max: 2048)
            try self.validate(self.executionRoleArn, name: "executionRoleArn", parent: name, min: 20)
            try self.validate(self.executionRoleArn, name: "executionRoleArn", parent: name, pattern: "^arn:(aws[a-zA-Z0-9-]*):iam::(\\d{12})?:(role((\\u002F)|(\\u002F[\\u0021-\\u007F]+\\u002F))[\\w+=,.@-]+)$")
            try self.validate(self.executionTimeoutMinutes, name: "executionTimeoutMinutes", parent: name, max: 1_000_000)
            try self.validate(self.executionTimeoutMinutes, name: "executionTimeoutMinutes", parent: name, min: 0)
            try self.jobDriver?.validate(name: "\(name).jobDriver")
            try self.validate(self.name, name: "name", parent: name, max: 256)
            try self.validate(self.name, name: "name", parent: name, min: 1)
            try self.validate(self.name, name: "name", parent: name, pattern: ".*\\S.*")
            try self.tags?.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^[A-Za-z0-9 /_.:=+@-]+$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, pattern: "^[A-Za-z0-9 /_.:=+@-]*$")
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 200)
        }

        private enum CodingKeys: String, CodingKey {
            case clientToken
            case configurationOverrides
            case executionRoleArn
            case executionTimeoutMinutes
            case jobDriver
            case name
            case tags
        }
    }

    public struct StartJobRunResponse: AWSDecodableShape {
        /// This output displays the application ID on which the job run was submitted.
        public let applicationId: String
        /// The output lists the execution role ARN of the job run.
        public let arn: String
        /// The output contains the ID of the started job run.
        public let jobRunId: String

        public init(applicationId: String, arn: String, jobRunId: String) {
            self.applicationId = applicationId
            self.arn = arn
            self.jobRunId = jobRunId
        }

        private enum CodingKeys: String, CodingKey {
            case applicationId
            case arn
            case jobRunId
        }
    }

    public struct StopApplicationRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "applicationId", location: .uri("applicationId"))
        ]

        /// The ID of the application to stop.
        public let applicationId: String

        public init(applicationId: String) {
            self.applicationId = applicationId
        }

        public func validate(name: String) throws {
            try self.validate(self.applicationId, name: "applicationId", parent: name, max: 64)
            try self.validate(self.applicationId, name: "applicationId", parent: name, min: 1)
            try self.validate(self.applicationId, name: "applicationId", parent: name, pattern: "^[0-9a-z]+$")
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct StopApplicationResponse: AWSDecodableShape {
        public init() {}
    }

    public struct TagResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("resourceArn"))
        ]

        /// The Amazon Resource Name (ARN) that identifies the resource to list the tags for. Currently, the supported resources are Amazon EMR Serverless applications and job runs.
        public let resourceArn: String
        /// The tags to add to the resource. A tag is an array of key-value pairs.
        public let tags: [String: String]

        public init(resourceArn: String, tags: [String: String]) {
            self.resourceArn = resourceArn
            self.tags = tags
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 1024)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 60)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:(aws[a-zA-Z0-9-]*):emr-serverless:.+:(\\d{12}):\\/applications\\/[0-9a-zA-Z]+(\\/jobruns\\/[0-9a-zA-Z]+)?$")
            try self.tags.forEach {
                try validate($0.key, name: "tags.key", parent: name, max: 128)
                try validate($0.key, name: "tags.key", parent: name, min: 1)
                try validate($0.key, name: "tags.key", parent: name, pattern: "^[A-Za-z0-9 /_.:=+@-]+$")
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, max: 256)
                try validate($0.value, name: "tags[\"\($0.key)\"]", parent: name, pattern: "^[A-Za-z0-9 /_.:=+@-]*$")
            }
            try self.validate(self.tags, name: "tags", parent: name, max: 200)
        }

        private enum CodingKeys: String, CodingKey {
            case tags
        }
    }

    public struct TagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct TotalResourceUtilization: AWSDecodableShape {
        /// The aggregated memory used per hour from the time job start executing till the time job is terminated.
        public let memoryGBHour: Double?
        /// The aggregated storage used per hour from the time job start executing till the time job is terminated.
        public let storageGBHour: Double?
        /// The aggregated vCPU used per hour from the time job start executing till the time job is terminated.
        public let vCPUHour: Double?

        public init(memoryGBHour: Double? = nil, storageGBHour: Double? = nil, vCPUHour: Double? = nil) {
            self.memoryGBHour = memoryGBHour
            self.storageGBHour = storageGBHour
            self.vCPUHour = vCPUHour
        }

        private enum CodingKeys: String, CodingKey {
            case memoryGBHour
            case storageGBHour
            case vCPUHour
        }
    }

    public struct UntagResourceRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "resourceArn", location: .uri("resourceArn")),
            AWSMemberEncoding(label: "tagKeys", location: .querystring("tagKeys"))
        ]

        /// The Amazon Resource Name (ARN) that identifies the resource to list the tags for. Currently, the supported resources are Amazon EMR Serverless applications and job runs.
        public let resourceArn: String
        /// The keys of the tags to be removed.
        public let tagKeys: [String]

        public init(resourceArn: String, tagKeys: [String]) {
            self.resourceArn = resourceArn
            self.tagKeys = tagKeys
        }

        public func validate(name: String) throws {
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, max: 1024)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, min: 60)
            try self.validate(self.resourceArn, name: "resourceArn", parent: name, pattern: "^arn:(aws[a-zA-Z0-9-]*):emr-serverless:.+:(\\d{12}):\\/applications\\/[0-9a-zA-Z]+(\\/jobruns\\/[0-9a-zA-Z]+)?$")
            try self.tagKeys.forEach {
                try validate($0, name: "tagKeys[]", parent: name, max: 128)
                try validate($0, name: "tagKeys[]", parent: name, min: 1)
                try validate($0, name: "tagKeys[]", parent: name, pattern: "^[A-Za-z0-9 /_.:=+@-]+$")
            }
            try self.validate(self.tagKeys, name: "tagKeys", parent: name, max: 200)
            try self.validate(self.tagKeys, name: "tagKeys", parent: name, min: 1)
        }

        private enum CodingKeys: CodingKey {}
    }

    public struct UntagResourceResponse: AWSDecodableShape {
        public init() {}
    }

    public struct UpdateApplicationRequest: AWSEncodableShape {
        public static var _encoding = [
            AWSMemberEncoding(label: "applicationId", location: .uri("applicationId"))
        ]

        /// The ID of the application to update.
        public let applicationId: String
        /// The CPU architecture of an application.
        public let architecture: Architecture?
        /// The configuration for an application to automatically start on job submission.
        public let autoStartConfiguration: AutoStartConfig?
        /// The configuration for an application to automatically stop after a certain amount of time being idle.
        public let autoStopConfiguration: AutoStopConfig?
        /// The client idempotency token of the application to update. Its value must be unique for each request.
        public let clientToken: String
        /// The capacity to initialize when the application is updated.
        public let initialCapacity: [String: InitialCapacityConfig]?
        /// The maximum capacity to allocate when the application is updated. This is cumulative across all workers at any given point in time during the lifespan of the application. No new resources will be created once any one of the defined limits is hit.
        public let maximumCapacity: MaximumAllowedResources?
        public let networkConfiguration: NetworkConfiguration?

        public init(applicationId: String, architecture: Architecture? = nil, autoStartConfiguration: AutoStartConfig? = nil, autoStopConfiguration: AutoStopConfig? = nil, clientToken: String = UpdateApplicationRequest.idempotencyToken(), initialCapacity: [String: InitialCapacityConfig]? = nil, maximumCapacity: MaximumAllowedResources? = nil, networkConfiguration: NetworkConfiguration? = nil) {
            self.applicationId = applicationId
            self.architecture = architecture
            self.autoStartConfiguration = autoStartConfiguration
            self.autoStopConfiguration = autoStopConfiguration
            self.clientToken = clientToken
            self.initialCapacity = initialCapacity
            self.maximumCapacity = maximumCapacity
            self.networkConfiguration = networkConfiguration
        }

        public func validate(name: String) throws {
            try self.validate(self.applicationId, name: "applicationId", parent: name, max: 64)
            try self.validate(self.applicationId, name: "applicationId", parent: name, min: 1)
            try self.validate(self.applicationId, name: "applicationId", parent: name, pattern: "^[0-9a-z]+$")
            try self.validate(self.clientToken, name: "clientToken", parent: name, max: 64)
            try self.validate(self.clientToken, name: "clientToken", parent: name, min: 1)
            try self.validate(self.clientToken, name: "clientToken", parent: name, pattern: "^[A-Za-z0-9._-]+$")
            try self.initialCapacity?.forEach {
                try validate($0.key, name: "initialCapacity.key", parent: name, max: 50)
                try validate($0.key, name: "initialCapacity.key", parent: name, min: 1)
                try validate($0.key, name: "initialCapacity.key", parent: name, pattern: "^[a-zA-Z]+[-_]*[a-zA-Z]+$")
                try $0.value.validate(name: "\(name).initialCapacity[\"\($0.key)\"]")
            }
            try self.validate(self.initialCapacity, name: "initialCapacity", parent: name, max: 10)
            try self.maximumCapacity?.validate(name: "\(name).maximumCapacity")
            try self.networkConfiguration?.validate(name: "\(name).networkConfiguration")
        }

        private enum CodingKeys: String, CodingKey {
            case architecture
            case autoStartConfiguration
            case autoStopConfiguration
            case clientToken
            case initialCapacity
            case maximumCapacity
            case networkConfiguration
        }
    }

    public struct UpdateApplicationResponse: AWSDecodableShape {
        /// Information about the updated application.
        public let application: Application

        public init(application: Application) {
            self.application = application
        }

        private enum CodingKeys: String, CodingKey {
            case application
        }
    }

    public struct WorkerResourceConfig: AWSEncodableShape & AWSDecodableShape {
        /// The CPU requirements for every worker instance of the worker type.
        public let cpu: String
        /// The disk requirements for every worker instance of the worker type.
        public let disk: String?
        /// The memory requirements for every worker instance of the worker type.
        public let memory: String

        public init(cpu: String, disk: String? = nil, memory: String) {
            self.cpu = cpu
            self.disk = disk
            self.memory = memory
        }

        public func validate(name: String) throws {
            try self.validate(self.cpu, name: "cpu", parent: name, max: 15)
            try self.validate(self.cpu, name: "cpu", parent: name, min: 1)
            try self.validate(self.cpu, name: "cpu", parent: name, pattern: "^[1-9][0-9]*(\\s)?(vCPU|vcpu|VCPU)?$")
            try self.validate(self.disk, name: "disk", parent: name, max: 15)
            try self.validate(self.disk, name: "disk", parent: name, min: 1)
            try self.validate(self.disk, name: "disk", parent: name, pattern: "^[1-9][0-9]*(\\s)?(GB|gb|gB|Gb)$")
            try self.validate(self.memory, name: "memory", parent: name, max: 15)
            try self.validate(self.memory, name: "memory", parent: name, min: 1)
            try self.validate(self.memory, name: "memory", parent: name, pattern: "^[1-9][0-9]*(\\s)?(GB|gb|gB|Gb)?$")
        }

        private enum CodingKeys: String, CodingKey {
            case cpu
            case disk
            case memory
        }
    }
}

// MARK: - Errors

/// Error enum for EMRServerless
public struct EMRServerlessErrorType: AWSErrorType {
    enum Code: String {
        case conflictException = "ConflictException"
        case internalServerException = "InternalServerException"
        case resourceNotFoundException = "ResourceNotFoundException"
        case serviceQuotaExceededException = "ServiceQuotaExceededException"
        case validationException = "ValidationException"
    }

    private let error: Code
    public let context: AWSErrorContext?

    /// initialize EMRServerless
    public init?(errorCode: String, context: AWSErrorContext) {
        guard let error = Code(rawValue: errorCode) else { return nil }
        self.error = error
        self.context = context
    }

    internal init(_ error: Code) {
        self.error = error
        self.context = nil
    }

    /// return error code string
    public var errorCode: String { self.error.rawValue }

    /// The request could not be processed because of conflict in the current state of the resource.
    public static var conflictException: Self { .init(.conflictException) }
    /// Request processing failed because of an error or failure with the service.
    public static var internalServerException: Self { .init(.internalServerException) }
    /// The specified resource was not found.
    public static var resourceNotFoundException: Self { .init(.resourceNotFoundException) }
    /// The maximum number of resources per account has been reached.
    public static var serviceQuotaExceededException: Self { .init(.serviceQuotaExceededException) }
    /// The input fails to satisfy the constraints specified by an AWS service.
    public static var validationException: Self { .init(.validationException) }
}

extension EMRServerlessErrorType: Equatable {
    public static func == (lhs: EMRServerlessErrorType, rhs: EMRServerlessErrorType) -> Bool {
        lhs.error == rhs.error
    }
}

extension EMRServerlessErrorType: CustomStringConvertible {
    public var description: String {
        return "\(self.error.rawValue): \(self.message ?? "")"
    }
}
